<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- <script src="./js/01-构造函数.js"></script> -->
    <!-- <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script> -->
    
</head>
<body>
    <script>
        // console.dir(axios);
        // let a = new axios.Axios();
        // console.log(a);


        /**
         * Axios 构造函数
         * CancelToken： 构造函数
         * 
         * 方法：
         * create
         * defaults
         * 
         * 请求方法
         * delete
         * get
         * patch
         * post
         * put
         * request:请求的基础方法
         * 
         * 拦截器
         * interceptors
         *    request:{
         *      handlers:[]
         *    }
         *    response:{
         *      hanlers:[]
         *    }
         * 
         * 
         * axios 具有 Axios 实例对象身上所有的属性和方法
         *       Axios.prototype.[request、put、post....]
         * 
         *       拦截器和 defaults
         * 
         */ 
        
        // 
        function InterceptorManager(){
            this.handlers = []
        }
        InterceptorManager.prototype.use = function(fulfilled, rejected){
            this.handlers.push({
                fulfilled,
                rejected
            })
        }
        
        
        function Axios(config){
            this.defaults = config;
            this.interceptors = {
                response: new InterceptorManager(),
                request:new InterceptorManager(),
            }
        }

        
        Axios.prototype.request = function(config){
            // 真正发送请求的函数
            const dispatchRequst = function(){
                return new Promise((resolve, reject)=>{
                    const xhr = new XMLHttpRequest()
                    xhr.open(config.method, config.url);
                    xhr.send()
                    xhr.onreadystatechange = function(){
                        if(xhr.readyState === 4) {
                            if(/^2\d{2}$/.test(xhr.status)){
                                resolve({
                                    data:xhr.response,
                                    status:xhr.status,
                                    config:config,
                                    headers:{},
                                    request:xhr
                                })
                            }else{
                                reject(xhr.status);
                            }
                        }
                    }
                })
            }
            const chain = [dispatchRequst, undefined];
            // 请求拦截器添加成功
            this.interceptors.request.handlers.forEach(item=>{
                chain.unshift(item.fulfilled,item.rejected);
            })
            // 相应拦截器
            this.interceptors.response.handlers.forEach(item=>{
                chain.push(item.fulfilled, item.rejected);
            })
            console.log('chain: ', chain);
            // 创建一个成功的promise激活chain链条
            let promise = Promise.resolve();
            while(chain.length){
                promise = promise.then(chain.shift(), chain.shift())
            }
            return promise;
        }
        const methods = ['put','post','delete','get','patch']
        methods.forEach(methodName=>{
            Axios.prototype[methodName] = function(){
                // 模拟Axios结构，没有方法具体实现
            }
        })
        console.dir(Axios);

        /**
         * 创建 axios
         * axios的身份是request函数,函数中的this，指向Axios的实例对象，因为要使用interceptors
         * 
         */
        function createInstance(config){
            // 创建一个Axios的实例对象
            const context = new Axios(config);// defaults interceptors
            // axios 是一个函数，axios({})发请求
            const instance = Axios.prototype.request.bind(context);
            // 给他添加上属性和方法
            // console.log(Object.keys(Axios.prototype));
            // Object.keys(Axios.prototype)
            // 将Axios.prototype原型上的方法，都添加给instance
            Object.keys(Axios.prototype).forEach(methodName=>{
                // console.log(methodName);
                instance[methodName] = Axios.prototype[methodName]
            })
            // 将实例对象身上的defaults和拦截器也给instance
            Object.keys(context).forEach(key=>{
                instance[key] = context[key]
            })
            // console.dir(instance);
            return instance;
        }

        const axios = createInstance({})

        axios.Axios = Axios;

        axios.create = function(config){
            return createInstance(config)
        }


        axios.interceptors.request.use(config1=>{
            return config1
        }, error1=>{
            return Promise.reject(error1);
        })

        axios.interceptors.request.use(config2=>{
            return config2
        }, error2=>{
            return Promise.reject(error2);
        })

        axios.interceptors.response.use(response1=>{
            return response1
        }, error1=>{
            return Promise.reject(error1);
        })

        axios.interceptors.response.use(response2=>{
            return response2.data
        }, error2=>{
            return Promise.reject(error2);
        })
        console.dir(axios);
        axios({method:'get', url:'https://api.uixsj.cn/hitokoto/get?type=social'}).then(data=>{
            console.log('data: ',data);
        })
        
    </script>
</body>
</html>